//
// Python bindings for scvCameraCore using pybind11
// Created for OrbbecSDK Python interface
//

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <pybind11/functional.h>
#include <opencv2/opencv.hpp>
#include "scvCameraCore.h"

namespace py = pybind11;


py::array mat_to_numpy(const cv::Mat& mat) {
    if (mat.empty()) {
        return py::array();
    }
    
    std::vector<size_t> shape;
    std::vector<size_t> strides;
    
    // 根据数据类型确定numpy数组类型
    int dtype;
    switch (mat.depth()) {
        case CV_8U: dtype = py::dtype::of<uint8_t>().num(); break;
        case CV_8S: dtype = py::dtype::of<int8_t>().num(); break;
        case CV_16U: dtype = py::dtype::of<uint16_t>().num(); break;
        case CV_16S: dtype = py::dtype::of<int16_t>().num(); break;
        case CV_32S: dtype = py::dtype::of<int32_t>().num(); break;
        case CV_32F: dtype = py::dtype::of<float>().num(); break;
        case CV_64F: dtype = py::dtype::of<double>().num(); break;
        default: throw std::runtime_error("Unsupported cv::Mat depth");
    }
    
    // 计算正确的形状和步长
    if (mat.channels() == 1) {
        // 单通道图像 (H, W)
        shape = {static_cast<size_t>(mat.rows), static_cast<size_t>(mat.cols)};
        strides = {static_cast<size_t>(mat.step), static_cast<size_t>(mat.elemSize1())};
    } else {
        // 多通道图像 (H, W, C)
        shape = {static_cast<size_t>(mat.rows), static_cast<size_t>(mat.cols), static_cast<size_t>(mat.channels())};
        strides = {
            static_cast<size_t>(mat.step),  // 行步长
            static_cast<size_t>(mat.elemSize1() * mat.channels()),  // 列步长
            static_cast<size_t>(mat.elemSize1())  // 通道步长
        };
    }
    
    // 创建numpy数组，使用引用策略避免内存泄漏
    return py::array(
        py::dtype(dtype),
        shape,
        strides,
        const_cast<void*>(static_cast<const void*>(mat.data)),
        py::cast(mat, py::return_value_policy::copy)
    );
}

// 从numpy数组创建cv::Mat
cv::Mat numpy_to_mat(py::array input) {
    py::buffer_info buf_info = input.request();
    
    // 确定OpenCV数据类型
    int cv_type;
    if (buf_info.format == py::format_descriptor<uint8_t>::format()) {
        cv_type = CV_8UC1;
    } else if (buf_info.format == py::format_descriptor<uint16_t>::format()) {
        cv_type = CV_16UC1;
    } else if (buf_info.format == py::format_descriptor<int16_t>::format()) {
        cv_type = CV_16SC1;
    } else if (buf_info.format == py::format_descriptor<int32_t>::format()) {
        cv_type = CV_32SC1;
    } else if (buf_info.format == py::format_descriptor<float>::format()) {
        cv_type = CV_32FC1;
    } else if (buf_info.format == py::format_descriptor<double>::format()) {
        cv_type = CV_64FC1;
    } else {
        throw std::runtime_error("Unsupported numpy array data type");
    }
    
    if (buf_info.ndim == 2) {
        return cv::Mat(static_cast<int>(buf_info.shape[0]), 
                      static_cast<int>(buf_info.shape[1]), 
                      cv_type, 
                      buf_info.ptr);
    } else if (buf_info.ndim == 3) {
        // 对于3维数组，假设是3通道
        return cv::Mat(static_cast<int>(buf_info.shape[0]), 
                      static_cast<int>(buf_info.shape[1]), 
                      cv_type + (static_cast<int>(buf_info.shape[2]) - 1) * 8, 
                      buf_info.ptr);
    }
    
    throw std::runtime_error("Unsupported numpy array dimensions");
}

// Python回调函数包装器
class PythonFrameCallback {
public:
    PythonFrameCallback(py::function callback) : callback_(callback) {}
    
    void operator()(const cv::Mat& color, const cv::Mat& depth) {
        py::gil_scoped_acquire acquire;
        callback_(mat_to_numpy(color), mat_to_numpy(depth));
    }
    
private:
    py::function callback_;
};

class PythonErrorCallback {
public:
    PythonErrorCallback(py::function callback) : callback_(callback) {}
    
    void operator()(SCVErrorCode error, const std::string& message) {
        py::gil_scoped_acquire acquire;
        callback_(static_cast<int>(error), message);
    }
    
private:
    py::function callback_;
};

PYBIND11_MODULE(scvOrbbec, m) {
    m.doc() = "OrbbecSDK Python bindings for scvCameraCore";
    
    // 注册cv::Mat类型
    py::class_<cv::Mat>(m, "Mat")
        .def(py::init<>())
        .def("empty", &cv::Mat::empty)
        .def_readonly("rows", &cv::Mat::rows)
        .def_readonly("cols", &cv::Mat::cols)
        .def("channels", &cv::Mat::channels)
        .def("depth", &cv::Mat::depth)
        .def("shape", [](const cv::Mat& mat) {
            if (mat.channels() == 1) {
                return py::make_tuple(mat.rows, mat.cols);
            } else {
                return py::make_tuple(mat.rows, mat.cols, mat.channels());
            }
        });

    // 枚举绑定
    py::enum_<SCVColorFormat>(m, "ColorFormat")
        .value("MJPG", SCVColorFormat::MJPG)
        .value("RGB888", SCVColorFormat::RGB888)
        .value("BGRA", SCVColorFormat::BGRA)
        .value("YUYV", SCVColorFormat::YUYV)
        .value("NV21", SCVColorFormat::NV21)
        .value("I420", SCVColorFormat::I420);

    py::enum_<SCVErrorCode>(m, "ErrorCode")
        .value("SUCCESS", SCVErrorCode::SUCCESS)
        .value("ERROR_INIT_FAILED", SCVErrorCode::ERROR_INIT_FAILED)
        .value("ERROR_DEVICE_NOT_FOUND", SCVErrorCode::ERROR_DEVICE_NOT_FOUND)
        .value("ERROR_STREAM_NOT_AVAILABLE", SCVErrorCode::ERROR_STREAM_NOT_AVAILABLE)
        .value("ERROR_INVALID_PARAMETER", SCVErrorCode::ERROR_INVALID_PARAMETER)
        .value("ERROR_TIMEOUT", SCVErrorCode::ERROR_TIMEOUT)
        .value("ERROR_DEVICE_DISCONNECTED", SCVErrorCode::ERROR_DEVICE_DISCONNECTED);

    // 结构体绑定
    py::class_<ColorProfile>(m, "ColorProfile")
        .def(py::init<>())
        .def(py::init<int, int, int, SCVColorFormat>(), 
             py::arg("width") = 640, py::arg("height") = 480, 
             py::arg("fps") = 15, py::arg("format") = SCVColorFormat::RGB888)
        .def_readwrite("width", &ColorProfile::width)
        .def_readwrite("height", &ColorProfile::height)
        .def_readwrite("fps", &ColorProfile::fps)
        .def_readwrite("format", &ColorProfile::format)
        .def("__repr__", [](const ColorProfile& p) {
            return "ColorProfile(width=" + std::to_string(p.width) + 
                   ", height=" + std::to_string(p.height) + 
                   ", fps=" + std::to_string(p.fps) + 
                   ", format=" + std::to_string(static_cast<int>(p.format)) + ")";
        });

    py::class_<DepthProfile>(m, "DepthProfile")
        .def(py::init<>())
        .def(py::init<int, int, int>(), 
             py::arg("width") = 640, py::arg("height") = 400, py::arg("fps") = 15)
        .def_readwrite("width", &DepthProfile::width)
        .def_readwrite("height", &DepthProfile::height)
        .def_readwrite("fps", &DepthProfile::fps)
        .def("__repr__", [](const DepthProfile& p) {
            return "DepthProfile(width=" + std::to_string(p.width) + 
                   ", height=" + std::to_string(p.height) + 
                   ", fps=" + std::to_string(p.fps) + ")";
        });

    py::class_<DeviceInfo>(m, "DeviceInfo")
        .def(py::init<>())
        .def_readwrite("name", &DeviceInfo::name)
        .def_readwrite("serialNumber", &DeviceInfo::serialNumber)
        .def_readwrite("firmwareVersion", &DeviceInfo::firmwareVersion)
        .def_readwrite("isConnected", &DeviceInfo::isConnected)
        .def("__repr__", [](const DeviceInfo& d) {
            return "DeviceInfo(name='" + d.name + 
                   "', serialNumber='" + d.serialNumber + 
                   "', firmwareVersion='" + d.firmwareVersion + 
                   "', isConnected=" + (d.isConnected ? "True" : "False") + ")";
        });

    // 主类绑定
    py::class_<scvCameraCore>(m, "CameraCore")
        .def(py::init<>())
        .def(py::init<const std::string&>(), py::arg("device_serial") = "")
        
        // 基本控制接口
        .def("initialize", py::overload_cast<>(&scvCameraCore::initialize))
        .def("initialize", py::overload_cast<const ColorProfile&, const DepthProfile&>(&scvCameraCore::initialize))
        .def("shutdown", &scvCameraCore::shutdown)
        .def("is_initialized", &scvCameraCore::isInitialized)
        .def("is_running", &scvCameraCore::isRunning)
        
        // 设备管理
        .def_static("enumerate_devices", &scvCameraCore::enumerateDevices)
        .def("connect_device", &scvCameraCore::connectDevice, py::arg("device_serial") = "")
        .def("disconnect_device", &scvCameraCore::disconnectDevice)
        .def("get_current_device_info", &scvCameraCore::getCurrentDeviceInfo)
        
        // 流控制
        .def("start_streams", &scvCameraCore::startStreams)
        .def("stop_streams", &scvCameraCore::stopStreams)
        .def("restart_streams", &scvCameraCore::restartStreams)
        
        // 帧获取接口 - 返回numpy数组
        .def("get_align_color_depth_mat", [](scvCameraCore& self) {
            cv::Mat colorMat, depthMat;
            SCVErrorCode result = self.getAlignColorDepthMat(colorMat, depthMat);
            return py::make_tuple(static_cast<int>(result), mat_to_numpy(colorMat), mat_to_numpy(depthMat));
        })
        .def("get_color_mat", [](scvCameraCore& self) {
            cv::Mat colorMat;
            SCVErrorCode result = self.getColorMat(colorMat);
            return py::make_tuple(static_cast<int>(result), mat_to_numpy(colorMat));
        })
        .def("get_depth_mat", [](scvCameraCore& self) {
            cv::Mat depthMat;
            SCVErrorCode result = self.getDepthMat(depthMat);
            return py::make_tuple(static_cast<int>(result), mat_to_numpy(depthMat));
        })
        
        // 配置接口
        .def("set_color_profile", &scvCameraCore::setColorProfile)
        .def("set_depth_profile", &scvCameraCore::setDepthProfile)
        .def("get_color_profile", &scvCameraCore::getColorProfile)
        .def("get_depth_profile", &scvCameraCore::getDepthProfile)
        
        // 回调接口
        .def("set_frame_callback", [](scvCameraCore& self, py::function callback) {
            auto wrapper = std::make_shared<PythonFrameCallback>(callback);
            self.setFrameCallback([wrapper](const cv::Mat& color, const cv::Mat& depth) {
                (*wrapper)(color, depth);
            });
        })
        .def("set_error_callback", [](scvCameraCore& self, py::function callback) {
            auto wrapper = std::make_shared<PythonErrorCallback>(callback);
            self.setErrorCallback([wrapper](SCVErrorCode error, const std::string& message) {
                (*wrapper)(error, message);
            });
        })
        .def("remove_frame_callback", &scvCameraCore::removeFrameCallback)
        .def("remove_error_callback", &scvCameraCore::removeErrorCallback)
        
        // 状态查询
        .def("is_color_stream_enabled", &scvCameraCore::isColorStreamEnabled)
        .def("is_depth_stream_enabled", &scvCameraCore::isDepthStreamEnabled)
        .def("get_color_fps", &scvCameraCore::getColorFPS)
        .def("get_depth_fps", &scvCameraCore::getDepthFPS)
        
        // 工具函数
        .def_static("get_error_string", &scvCameraCore::getErrorString)
        .def("set_log_level", &scvCameraCore::setLogLevel);

    // 便利函数
    m.def("get_error_string", &scvCameraCore::getErrorString, "Get error string from error code");
    m.def("enumerate_devices", &scvCameraCore::enumerateDevices, "Enumerate all available devices");
}